package com.dz.lm.common.utils.json;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * JsonUtils共聚类
 * @author zhanghairong
 * @since 2019-05-28
 */
public final class JsonUtils {
	private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);
	public static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";

	static ObjectMapper objectMapper = new ObjectMapper();
	static{
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

		SerializationConfig serConfig = objectMapper.getSerializationConfig();
        serConfig.with(new SimpleDateFormat(DATEFORMAT));

        //for quoted
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
	}


	/**
	 *
	 * @param josnStr
	 * @return
	 * @throws RuntimeException
	 */
	public static Map<String, Object> readValue(String josnStr) throws RuntimeException{
		try {
			return objectMapper.readValue(josnStr, HashMap.class);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}


	/**
	 *
	 * @param <T>
	 * @param josnStr
	 * @param cls
	 * @return
	 * @throws RuntimeException
	 */
	public static <T>  T readValue(String josnStr, Class<T> cls) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, cls);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}


	public static <T>  T readValue(String josnStr, TypeReference<T> t) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, t);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}


	public static <T>  T readValue(String josnStr, JavaType t) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, t);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}




	/**
	 *
	 * @param <T>
	 * @param josnStr
	 * @param cls
	 * @return
	 * @throws RuntimeException
	 */
	public static <T>  T readValue(InputStream josnStr, Class<T> cls) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, cls);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}

	public static <T>  T readValue(InputStream josnStr,  TypeReference<T> t) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, t);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}

	public static <T>  T readValue(InputStream josnStr,  JavaType t) throws RuntimeException{
		try {
			return (T)objectMapper.readValue(josnStr, t);
		} catch (JsonParseException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}

	public static String writeValue(Object entity) throws RuntimeException{
		return writeValue(entity, false);
	}

	/**
	 *
	 * @param entity
	 * @return
	 * @throws RuntimeException
	 */
	public static String writeValue(Object entity, boolean prettyPrint) throws RuntimeException{
		try {
			StringWriter sw = new StringWriter();
			JsonGenerator jg = objectMapper.getJsonFactory().createJsonGenerator(sw);
			if (prettyPrint) {
				jg.useDefaultPrettyPrinter();
			}
			objectMapper.writeValue(jg, entity);
			return sw.toString();
		} catch (JsonGenerationException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e);
		}
	}
	/**
	 *
	 * @param <T>
	 * @param josnStr
	 * @param cls
	 * @return
	 * @throws RuntimeException
	 */
	public static Map<String, Object> getParameter(String josnStr) throws RuntimeException{
		HashMap<String, Object> paramJsonMap = new HashMap<String, Object>();
		String params[] = null;
		if (josnStr != null && !"".equals(josnStr)) {
			params = josnStr.split("&");
			for (String param : params) {
				paramJsonMap.put(param.split("=")[0], param.split("=")[1]);
			}
		} else {
			return new HashMap<String, Object>();
		}
		return paramJsonMap;
	}

	public static String getJsonStr(int count){
		return "{\"result\":" + count + " }";
	}


	public static JsonFactory getJsonFactory(){
		return objectMapper.getJsonFactory();
	}

	public static ObjectMapper getObjectMapper(){
		return objectMapper;
	}

}
